Vue基本用法
前置知识
什么是Vue
中文官网 Vue是一种渐进式JavaScript框架
声明式渲染 -> 组件系统 -> 客户端路由 -> 集中式状态管理 -> 项目构建
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<!-- 引入 axios -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<!-- 引入 qs -->
<script src="https://cdn.bootcss.com/qs/6.5.1/qs.min.js"></script>
const qs = Qs // 引入QS库把请求参数转成表单形式
axios.defaults.timeout = 3000; // 设置超时时间
// 设置请求的基准URL地址
axios.defaults.baseURL = 'http://localhost:8080/';
// 使请求可以携带 Cookie
axios.interceptors.request.use(config => {
config.withCredentials = true;
return config;
});
new Vue({
el: '#app',
data() {
return {
username: '',
password: ''
}
},
methods: {
login() {
axios.post('/login', qs.stringify({
username: this.username,
password: this.password
}), {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.then((result) => {
console.log(result);
}).catch((err) => {
console.log(err);
});
}
},
})
生命周期(钩子函数)
Vue的生命周期
其中红色部分都是可以插入钩子的地方
参考自官方文档
- 挂载(初始化相关属性)
时期 | 作用 |
---|---|
beforeCreate | 在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。 |
create | 在实例创建完成后被立即调用。$el 属性 还尚不可用 |
beforeMount | 在挂载开始之前被调用:相关的 回调函数 首次被调用。 |
mounted | 实例被挂载后调用,这时 el 被新创建的 vm.$el 替换了。并挂载到实例上去之后调用该钩子 |
- 更新(元素或组件的变更操作)
时期 | 作用 |
---|---|
beforeUpdate | 数据更新时调用,发生在虚拟 DOM 打补丁之前。 |
update | 由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。(数据已经更新了) |
- 销毁(销毁相关属性)
时期 | 作用 |
---|---|
beforeDestroy | 实例销毁之前调用。在这一步,实例仍然完全可用。 |
destroy | 实例销毁后调用。该钩子被调用后,对应 Vue 实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁。 |
什么是MVVM
原本的 MVC 是以下的模式
而 MVVM 是 MVC 的一种变体
M:Model V:View VM:ViewModel
在MVVM架构里是不允许数据和视图直接通信的,只能通过ViewModel来通信,而ViewModel就是定义了一个Observer观察者
- ViewModel能够观察到数据的变化,并对视图对应的内容进行更新
- ViewModel能够监听到视图的变化,并能够通知数据发生改变
实际上就是类似于AndroidStudio那样的数据绑定机制,亦或者说类似于Spring的IOC概念意义,在需要数据的地方使用ViewModel,从而方便传入数据,而无需手动的传入数据
vue各版本的区别
# 压缩后的代码
vue.min.js
# 可看的源码(开发版,有完整的提示信息)
vue.js
vue主要的属性
el 挂载点
el 挂载点 用来绑定 DOM,Vue 会管理 el 选择命中的元素及其内部的后代元素 使用的语法和 css 是一样的,但是注意不可以在 body 和 html 标签上使用,但是可以挂载在其他的元素上
<div id="app"></div>
<script>
let vm = new Vue({
el: '#app'
})
</script>
data 数据
用来填充数据,data 中可以写复杂类型的数据(数组,对象等) 渲染复杂类型数据时,遵守 JS 的语法即可 要读取数据就直接读取 data 里的属性就好了
<script>
let vm = new Vue({
el: '#app',
data: {
type: 'A'
},
})
</script>
method
这里面写绑定的方法
<body>
<div id="app">
<button v-on:click="sayhell">click this</button>
<!-- 或者直接调用 -->
{{sayhell()}}
</div>
<script src="/node_modules/vue/dist/vue.min.js"></script>
<script>
let vm = new Vue({
el: '#app',
methods: {
sayhell: function () {
console.log('hello');
}
},
})
</script>
</body>
内容绑定,事件绑定
v-text 插入文本
设置标签的文本值(textContent)
简写就是{{msg}}
<div id='app'>
<h2 v-text="message + '这是字符串拼接'"></h2>
</div>
let app = new Vue({
el:'#app',
data: {
message: 'hello vue'
}
})
实际上直接用{{msg}}
也可以
<div id='app'>
<h2>
{{message + "这是字符串拼接"}}
</h2>
</div>
v-html 插入标签
设置标签的innerHTML
如果只是插入普通文本则与上面的v-text
属性没有区别,但是插入标签的话必须用这个v-html
否则解析不出来
<div id='app'>
<p v-html="message"></p>
</div>
let app = new Vue({
el:'#app',
data: {
message: '<h1>hello vue </h1>'
}
})
v-on 绑定事件
为元素绑定事件(就是监听事件)
语法:
<div id='app'>
<input type="button" value="按钮名称" v-on:事件名="方法">
</div>
v-on
可以简写使用 @
字符
例如
<input type="button" value="按钮名称" @click="方法">
let app = new Vue({
el:'#app',
data: {
food: '西兰花'
},
methods: {
方法: function(){
/**
如果想在方法里修改某些属性值则使用this指针,
因为本质上一个Vue就是一个对象,所以通过this指针来提高作用域
Vue里的this有点特殊,后面讲
*/
this.food = '青瓜'
}
}
})
常用的事件: 事件名 | 作用 ---------|---------- click | 点击 monseenter | 鼠标移动 dblclick | 鼠标双击
参数:event
用在普通元素上时,只能监听原生 DOM 事件。用在自定义元素组件上时,也可以监听子组件触发的自定义事件。
综合案例:计数器
<div id='app'>
<button @click="add">+</button>
<span>{{number}}</span>
<button @click="sub">-</button>
</div>
let app = new Vue({
el:'#app',
data: {
number: 0
},
methods: {
add:function(){
this.number++
},
sub:function(){
this.number--
}
},
})
显示切换,属性绑定
v-show 显示和隐藏
根据表达值的真假,切换元素的显示和隐藏
<div id='app'>
<button @click="show">显示/隐藏</button>
<h1 v-show="isShow">看得见这句话吗?</h1>
</div>
原理是通过css来隐藏的
<h1 style="display: none;">看得见这句话吗?</h1>
let app = new Vue({
el:'#app',
data: {
isShow: false
},
methods: {
show:function(){
this.isShow = !this.isShow
}
},
})
v-if 显示和隐藏
根据表达值的真假,切换元素的显示和隐藏(操纵dom元素)
语法与上基本一致,只是把show改成了if,与上面的区别就是show是通过改css样式来隐藏的,而if是直接从dom树里剔除掉这个元素
所以频繁切换的元素用上面那个v-show
,因为操纵dom树对性能的消耗较大
<div id='app'>
<button @click="show">显示/隐藏</button>
<h1 v-show="isShow">看得见这句话吗?</h1>
</div>
let app = new Vue({
el:'#app',
data: {
isShow: false
},
methods: {
show:function(){
this.isShow = !this.isShow
}
},
})
除了if还可以使用else属性来完成逻辑判断
<div id="app">
<h1 v-if="type==='A'">YES</h1>
<h1 v-else-if="type==='B'">NO</h1>
<h1 v-else>WOW</h1>
</div>
<script src="/node_modules/vue/dist/vue.min.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
type: 'A'
},
})
</script>
v-bind 绑定属性
参考官方的v-bind
用来设置元素的属性,比如src、title、class
语法 v-bind:属性名=表达式
缩写::属性名=表达式
<div id='app'>
<button @click="change">更改图片地址</button>
<img v-bind:src="imageSrc"
:title=" 'this is image ' + imageTitle"
:class="{active:isActive}">
</div>
{active:isActive}
当isActive等于true时class的值为active否则为空
let app = new Vue({
el:'#app',
data: {
imageSrc: 'https://image.alsritter.icu/2020/06/19/NuPrVJ.jpg',
imageTitle: '标题',
isActive: true
},
methods: {
change:function(){
this.imageSrc = 'https://image.alsritter.icu/2020/06/19/NuP226.jpg'
}
},
})
v-bind 绑定样式
方式一
实际上和上面的那个用法是基本一致的,只是动态的更改class的内容来动态更换css
.active {
height: 100px;
width: 100px;
border: 1px solid red;
}
.change {
background-color: blueviolet;
}
<!-- 这里的 {active: isActive , change: isChange} 和上面绑定属性的那个用法是一样的-->
<div id="app">
<div :class="{active: isActive , change: isChange}"></div>
<button @click='show'>显示方块</button>
<button @click='handle'>改变颜色</button>
</div>
let vm = new Vue({
el: '#app',
data: {
isActive: true,
isChange: false
},
methods: {
show: function(){
this.isActive = !this.isActive
},
handle: function(){
this.isChange = !this.isChange
}
},
})
方式二
除了上面那种直接绑定对象的方式,还可以使用标签的style属性
<div :style="{border: borderStyle , width: widthStyle , height: heightStyle}"></div>
方式三
最后还有一种直接传递对象到style属性的形式,注意上面的是花括号,这里是中括号
<div :style="[objStyle, obj2Style]"></div>
在vue的data区里加上
data:{
objStyle:{
border: '1px solid red',
width: '100px',
height: '100px'
},
obj2Style:{
...
}
}
综合案例:切换图片
<div id='app'>
<button @click="last">上一张</button>
<img v-bind:src="imageSrc[index]" style="width: 300px;">
<button @click="next">下一张</button>
</div>
let app = new Vue({
el: '#app',
data: {
imageSrc: [
'https://image.alsritter.icu/2020/06/19/Nu9RF1.jpg',
'https://image.alsritter.icu/2020/06/19/Nu9goR.jpg',
'https://image.alsritter.icu/2020/06/19/NuPfKO.jpg',
'https://image.alsritter.icu/2020/06/19/NuP226.jpg',
'https://image.alsritter.icu/2020/06/19/NuPsa9.jpg'
],
index: 0
},
methods: {
last: function () {
this.index <= 0 ? this.index:this.index--
},
next: function () {
this.index >= (this.imageSrc.length - 1) ? this.index : this.index++
}
},
})
列表循环,表单元素绑定
v-for 循环语句
使用有两种形式
<div id="app">
<!-- 第一种形式 -->
<li v-for="item in items">
{{item.message}}
</li>
<!-- 第二种形式 -->
<li v-for="(item, index) in items" :key="index">
{{items[index].message}}
</li>
</div>
vue循环的不是自身,而是包含了 item
的子标签
let vm = new Vue({
el: '#app',
data: {
items: [
{message: '项目一'},
{message: '项目二'},
{message: '项目三'}
]
},
})
key的作用:帮助Vue区分不同的元素,从而提高性能,原理就是为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素(就是当数据变更时无需重新循环),需要为每项提供一个唯一 key
所以尽可能的在使用 v-for 时提供 key
<li v-for="(item, index) in items" :key="index.id">{{item}} + '----' {{index}}</li>
v-on补充
传递自定义参数,事件修饰符 参考自官方文档 用法 案例参考黑马教程
传递参数
例:
<div id='app'>
<button @click="test('小明','小美')">测试v-on事件修饰符</button>
</div>
let app = new Vue({
el: '#app',
methods: {
test: function (p1,p2) {
console.log(`hi ${p1} 和 ${p2}`)
}
},
})
事件修饰符
就是事件的后面跟上 .修饰符
可以对事件进行限制
事件修饰符更多用法参考官方文档的--事件修饰符
.once
.once
只有在第一次点击时会执行,再次点击不会起作用
<div v-on:click.once='alert("1")'></div>
.stop
.stop
- 调用 event.stopPropagation()
。阻止函数的传递
当出现下面这种情况时 点击子级的div会,先弹出2,再弹出1
<div v-on:click='alert("1")' style="width: 100%;height: 45px;background-color: black;">
<div v-on:click="alert('2')" style='width: 80%;margin-left: 10%;background-color: white;'>
123
</div>
</div>
加上.stop
之后 就只会弹出2,不会弹出1 了
<div v-on:click.stop="alert('2')" style='width: 80%;margin-left: 10%;background-color: white;'>
123
</div>
.prevent
.prevent
- 调用 event.preventDefault()
。 就是阻止默认程序,比如form表单中的summit提交按钮,会自己提交,加上之后 直接不让提交了,也不跳转,只是执行自己命名的函数
<input type="submit" value="提交" @click.prevent="handle">
.capture 和 .self
这两个参考 vue中的.capture和.self区分,初步理解
.capture
- 添加事件侦听器时使用 capture 模式。
.self
- 只当事件是从侦听器绑定的元素本身触发时才触发回调。
按键修饰符
按键修饰符更多用法参考官方文档的--按键修饰符
.{keyCode | keyAlias}
- 只当事件是从特定键触发时才触发回调。(就是监听按键)
这个.{keyCode | keyAlias}
使用例:
<!-- 这样按下回车(enter)就会执行这个sayHi函数 -->
<input type="text" @keyup.enter="sayHi">
<!-- Alt + C -->
<input @keyup.alt.67="clear">
<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>
鼠标修饰符
.left
- (2.2.0) 只当点击鼠标左键时触发。
.right
- (2.2.0) 只当点击鼠标右键时触发。
.middle
- (2.2.0) 只当点击鼠标中键时触发。
.passive
- (2.3.0) 以 { passive: true }
模式添加侦听器
v-model 双向绑定
获取和设置表单元素的值(双向数据绑定)
<div id="app">
<input type="text" v-model="message"> {{message}}
</div>
let vm = new Vue({
el: '#app',
data: {
message: "12345"
}
})
绑定下拉框
注意:如果v-model
表达式的初始值未能匹配任何选项,<select>
元素会被渲染为未选择状态
在ios中,这会使用户无法选择第一个选项。因为这样的情况下,IOS不会触发change事件,所以最好在顶部加上一个值为空的禁选项
<div id="app">
<select v-model="message">
<option value="" disabled>请选择</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
{{message}}
</div>
let vm = new Vue({
el: '#app',
data: {
message: ""
}
})
表单域修饰符
- number:转化为数值
- trim:去掉开始和结尾的空格
- lazy:将input事件切换为change事件,就是原本的事件时输入时就触发,而lazy是当失去焦点时才触发(例如注册时验证用户名是否被占用时就很有用)
例如:将字符型转化为number
<div id="app">
<input type="number" v-model.number="age">
<button @click="handle">点击</button>
</div>
测试代码
let vm = new Vue({
el: '#app',
data: {
age: ''
}, methods: {
handle: function () {
console.log(this.age + 100)
}
},
})
表单操作
基于Vue的表单操作 ,就以下面的例子来参考如何绑定表单中的元素
- input 单行文本
- textarea 多行文本
- select 下拉多选
- radio 单选框
- checkbox 多选框
使用的测试表单
<div id="app">
<form action="#" method="POST">
<div>
<span>姓名:</span><input type="text" v-model="uname">
</div>
<div>
<span>性别:</span>
<!-- 这里的label标签的作用就是点击label标签的文本后,光标跳转到for属性中id所对应的标签处 -->
<input type="radio" id="male" name="sex" value="1" v-model="gender">
<label for="male">男</label>
<input type="radio" id="female" name="sex" value="2" v-model="gender">
<label for="female">女</label>
</div>
<div>
<span>爱好:</span>
<!-- 因为本来就不用默认表单提交,所以可以不设置name,
上面的radio设置name是为了防止多选,这个本来就是多选框,所以随意了
且注意:多选框的data要设置成数组 [] -->
<input type="checkbox" id="ball" v-model="hobby" value="1" >
<label for="ball">篮球</label>
<input type="checkbox" id="sing" v-model="hobby" value="2">
<label for="sing">唱歌</label>
<input type="checkbox" id="code" v-model="hobby" value="3">
<label for="code">敲代码</label>
</div>
<div>
<span>职业:</span>
<!-- 如果想要多选则加上multiple属性 (multiple="true"),按shift就能多选了 -->
<select v-model="occupation">
<option disabled value="0">请选择职业</option>
<option value="1">教师</option>
<option value="2">程序员</option>
<option value="3">学生</option>
<option></option>
</select>
</div>
<div>
<span>个人简历:</span>
<!-- 这个多行文本绑定和单行文本差不多
描述的单词: description 缩写 desc -->
<textarea cols="30" rows="10" v-model="desc"></textarea>
</div>
<div>
<input type="submit" value="提交" @click.prevent="handle">
</div>
</form>
</div>
let vm = new Vue({
el: '#app',
data: {
uname: 'alsritter',
gender: 1,
hobby: [],
occupation: 0,
desc: ""
},methods: {
handle: function(){
console.log(this.uname)
}
},
})